/*
 * DHCPServer.hpp
 *
 *  Created on: 21.04.2011
 *      Author: mifodix
 */

#ifndef DHCPSERVER_HPP_
#define DHCPSERVER_HPP_

#ifndef __cplusplus
#error Need C++-compile to process this file
#endif

#include "ConfigParser.hpp"
#include "Logger.hpp"
#include "PacketEditor.hpp"
#include "Settings.hpp"
#include "SocketUDP.hpp"
#include <boost/thread.hpp>
#include <list>
#include "MacIP.hpp"
#include "MacIPTimes.hpp"

#define SERVER_PORT 67
#define CLIENT_PORT 68
#define ADDR_STR_SIZE 16
//предложение IP будет устаревать через 5 минут
#define OFFER_EXPIRATION_TIME 600

#define BOOT_REPLY 2

//типы сообщений
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNAK 6
#define DHCPRELEASE 7
#define DHCPINFORM 8

//коды опций
#define OPTION_SUBNET_MASK 1
#define OPTION_ROUTER 3
#define OPTION_DOMAIN_NAME_SERVER 6
#define OPTION_REQUEST_IP 50
#define OPTION_REQUEST_TIME 51
#define OPTION_MESSAGE_TYPE 53
#define OPTION_SERVER_IDENTIFIER 54
#define OPTION_MESSAGE 56
/*
 *
 */
class DHCPServer
{
private:
	static Settings *settings;

	static boost::shared_mutex offeredMutex;
	static boost::shared_mutex boundedMutex;
	static boost::mutex broadcastListenerMutex;
	static boost::mutex broadcastSenderMutex;
	static boost::mutex nextDynIPMutex;

	static volatile uint32_t nextDynIP;
	static std::list<MacIPTimes> boundedAddr;
	static std::list<MacIPTimes> offeredAddr;

	static SocketUDP broadcastListener;
	static SocketUDP broadcastSender;

	static uint32_t FindIP(std::list<MacIPTimes> list, const char *mac);
	static uint32_t FindLease(std::list<MacIPTimes> list, const char *mac);
	static bool IsIPAllocated(std::list<MacIPTimes> list, uint32_t ip);
	static bool IsIPAvailable(uint32_t ip);
	static bool OfferIPnLease(const char *mac, uint32_t &ip, uint32_t &lease);
	static bool BindIPnLease(const char *mac, uint32_t &ip, uint32_t &lease);
	static void thread_func(PacketEditor p);
	static void FreeOldOffers();
	static void FreeExpiredBoundings();
	static bool ExtendBounding(const char *mac);
	static PacketEditor* AddOptionsFromSettings(PacketEditor *p);

	static PacketEditor* ProcessDiscover(PacketEditor p);
	static PacketEditor* ProcessRequest(PacketEditor p);
	static void ProcessDecline(PacketEditor p);
	static void ProcessRelease(PacketEditor p);
	static PacketEditor* ProcessInform(PacketEditor p);

	static DHCPServer* theSingleInstance;//шаблон одиночка
	DHCPServer();

public:
	static DHCPServer* GetInstance();
	static void start(const char *cfgFilename);
	virtual ~DHCPServer();
};

#endif /* DHCPSERVER_HPP_ */
